home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / cfortune.zip / YOW.C < prev    next >
C/C++ Source or Header  |  1989-05-25  |  4KB  |  214 lines

  1. /* $Header$ */
  2.  
  3. # include    <sys/types.h>
  4. # include    <stdio.h>
  5. # include    <sys/file.h>
  6. # include    "strfile.h"
  7.  
  8. # define    TRUE    1
  9. # define    FALSE    0
  10. # define    bool    short
  11.  
  12. # define    MINW    6        /* minimum wait if desired */
  13. # define    CPERS    20        /* # of chars for each sec */
  14. # define    SLEN    160        /* # of chars in short fortune */
  15.  
  16. # define    FORTFILE    "/usr/games/lib/zippy.dat"
  17.  
  18. bool    Wflag        = FALSE,    /* wait desired after fortune */
  19.     Sflag        = FALSE,    /* short fortune desired */
  20.     Lflag        = FALSE;    /* long fortune desired */
  21.  
  22. char    *Fortfile    = FORTFILE,    /* fortune database */
  23.     *Usage[]    = {
  24.        "usage:  yow [ - ] [ -wsloa ] [ file ]",
  25.        "    - - give this summary of usage",
  26.        "    w - have program wait after printing message in order",
  27.        "        to give time to read",
  28.        "    s - short fortune only",
  29.        "    l - long fortune only",
  30.     NULL
  31.     };
  32.  
  33. long    Seekpts[2];            /* seek pointers to fortunes */
  34.  
  35. FILE    *Inf;                /* input file */
  36.  
  37. STRFILE    Tbl;                /* input table */
  38.  
  39. time_t    time();
  40.  
  41. main(ac, av)
  42. int    ac;
  43. char    *av[];
  44. {
  45.     register char    c;
  46.     register int    nchar = 0;
  47.     register int    i;
  48.  
  49.     getargs(ac, av);
  50.     if ((Inf = fopen(Fortfile, "r+")) == NULL) {
  51.         perror(Fortfile);
  52.         exit(-1);
  53.     }
  54.     fread((char *) &Tbl, sizeof Tbl, 1, Inf);    /* NOSTRICT */
  55.     if (Tbl.str_longlen <= SLEN && Lflag) {
  56.         puts("Sorry, no long strings in this file");
  57.         exit(0);
  58.     }
  59.     if (Tbl.str_shortlen > SLEN && Sflag) {
  60.         puts("Sorry, no short strings in this file");
  61.         exit(0);
  62.     }
  63.  
  64.     /*
  65.      * initialize the pointer to the first -o fortune if need be.
  66.      */
  67.     if (Tbl.str_delims[2] == 0)
  68.         Tbl.str_delims[2] = Tbl.str_delims[0];
  69.  
  70.     do {
  71.         getfort();
  72.     } while ((Sflag && !is_short()) || (Lflag && !is_long()));
  73.  
  74.     fseek(Inf, Seekpts[0], 0);
  75.     while (c = getc(Inf)) {
  76.         nchar++;
  77.         putchar(c);
  78.     }
  79.     fflush(stdout);
  80.     fseek(Inf, 0L, 0);
  81. #ifdef    LOCK_EX
  82.     /*
  83.      * if we can, we exclusive lock, but since it isn't very
  84.      * important, we just punt if we don't have easy locking
  85.      * available.
  86.      */
  87.     flock(fileno(Inf), LOCK_EX);
  88. #endif    LOCK_EX
  89.     fwrite(&Tbl, 1, sizeof Tbl, Inf);
  90. #ifdef    LOCK_EX
  91.     flock(fileno(Inf), LOCK_UN);
  92. #endif    LOCK_EX
  93.     if (Wflag)
  94.         sleep(max((int) nchar / CPERS, MINW));
  95.     exit(0);
  96. }
  97.  
  98. /*
  99.  * is_short:
  100.  *    Return TRUE if fortune is "short".
  101.  */
  102. is_short()
  103. {
  104.     register int    nchar;
  105.  
  106.     if (!(Tbl.str_flags & (STR_RANDOM | STR_ORDERED)))
  107.         return (Seekpts[1] - Seekpts[0] <= SLEN);
  108.     fseek(Inf, Seekpts[0], 0);
  109.     nchar = 0;
  110.     while (getc(Inf))
  111.         nchar++;
  112.     return (nchar <= SLEN);
  113. }
  114.  
  115. /*
  116.  * is_long:
  117.  *    Return TRUE if fortune is "long".
  118.  */
  119. is_long()
  120. {
  121.     register int    nchar;
  122.  
  123.     if (!(Tbl.str_flags & (STR_RANDOM | STR_ORDERED)))
  124.         return (Seekpts[1] - Seekpts[0] > SLEN);
  125.     fseek(Inf, Seekpts[0], 0);
  126.     nchar = 0;
  127.     while (getc(Inf))
  128.         nchar++;
  129.     return (nchar > SLEN);
  130. }
  131.  
  132. /*
  133.  *    This routine evaluates the arguments on the command line
  134.  */
  135. getargs(ac, av)
  136. register int    ac;
  137. register char    *av[];
  138. {
  139.     register int    i;
  140.     register char    *sp;
  141.     register int    j;
  142.     register short    bad = 0;
  143.  
  144.     for (i = 1; i < ac; i++)  {
  145.         if (av[i][0] != '-') {
  146.             setuid(getuid());
  147.             setgid(getgid());
  148.             Fortfile = av[i];
  149.         }
  150.         else if (av[i][1] == '\0') {
  151.             j = 0;
  152.             while (Usage[j] != NULL)
  153.                 puts(Usage[j++]);
  154.             exit(0);
  155.             /* NOTREACHED */
  156.         }
  157.         else
  158.             for (sp = &av[i][1]; *sp != '\0'; sp++)
  159.                 switch (*sp) {
  160.                   case 'w':    /* give time to read */
  161.                     Wflag++;
  162.                     break;
  163.                   case 's':    /* short ones only */
  164.                     Sflag++;
  165.                     Lflag=0;
  166.                     break;
  167.                   case 'l':    /* long ones only */
  168.                     Lflag++;
  169.                     Sflag=0;
  170.                     break;
  171.                   default:
  172.                     printf("unknown flag: '%c'\n", *sp);
  173.                     bad++;
  174.                     break;
  175.                 }
  176.     }
  177.     if (bad) {
  178.         printf("use \"%s -\" to get usage\n", av[0]);
  179.         exit(-1);
  180.     }
  181. }
  182.  
  183. /*
  184.  * getfort:
  185.  *    Get the fortune data file's seek pointer for the next fortune.
  186.  */
  187. getfort()
  188. {
  189.     register int    fortune;
  190.  
  191.     /*
  192.      * Make sure all values are in range.
  193.      */
  194.  
  195.     if (Tbl.str_delims[1] >= Tbl.str_delims[0])
  196.         Tbl.str_delims[1] = 0;
  197.     if (Tbl.str_delims[2] >= Tbl.str_numstr)
  198.         Tbl.str_delims[2] = Tbl.str_delims[0];
  199.  
  200.         if (rnd(Tbl.str_numstr) < Tbl.str_delims[0])
  201.             fortune = Tbl.str_delims[1]++;
  202.         else
  203.             fortune = Tbl.str_delims[2]++;
  204.  
  205.     fseek(Inf, (long)(sizeof Seekpts[0]) * fortune + sizeof Tbl, 0);
  206.     fread((char *) Seekpts, (sizeof Seekpts[0]), 2, Inf);
  207. }
  208.  
  209. max(i, j)
  210. register int    i, j;
  211. {
  212.     return (i >= j ? i : j);
  213. }
  214.